package com.luokangtao.common.intercept;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.luokangtao.common.annotation.Auth;
import com.luokangtao.common.entity.StatusCode;
import com.luokangtao.common.handler.BaseException;
import com.luokangtao.common.util.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 拦截器
 * 最常用的登录拦截、或是权限校验、或是防重复提交
 * @author luokangtao
 * @create 2019-07-26 11:00
 */
@Slf4j
public class UserAuthInterceptor extends HandlerInterceptorAdapter {

    /**
     * preHandle在执行Controller之前执行
     * 返回true，则继续执行Contorller
     * 返回false则请求中断。
     * @param request
     * @param response
     * @param handler
     * @return
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        log.info("拦截器开始执行:====================================");
        if (!(handler instanceof HandlerMethod)) {
            log.info("拦截器:HandlerMethod==================================");
            //决解启动报错:
            //java.lang.ClassCastException: org.springframework.web.servlet.resource.ResourceHttpRequestHandler cannot be cast to org.springframework.web.method.HandlerMethod
            return true;
        }else {
            //获取拦截的方法
            Method method = ((HandlerMethod) handler).getMethod();
            //判断是否有自定义注解
            //Auth annotation = method.getDeclaredAnnotation(Auth.class);
            //用于在AnnotatedElements上查找注解，元注解和可重复注解的常规实用程序方法。
            // AnnotatedElementUtils为Spring的元注解编程模型定义了公共API，并支持注解属性覆盖。
            // 如果您不需要支持注解属性覆盖，请考虑使用AnnotationUtils。
            Auth annotation = AnnotatedElementUtils.getMergedAnnotation(method, Auth.class);
            log.info("判断是否有自定义注解:[{}]",annotation);
            if(annotation==null){
                log.info("没有注解:直接放行");
                return true;
            }
            //判断是否登陆权限
            boolean value = annotation.value();
            log.info("判断是否当前用户是否登陆需要登陆:[{}]",value);
            if(value){
                //获取请求头内容
                String authorization = request.getHeader("Authorization");
                log.info("获取头部信息Authorization:[{}]",authorization);
                //hasBlank会把不可见字符也算做空(判断字段是否有空的)
                if(StrUtil.hasBlank(authorization)){
                    throw new BaseException(StatusCode.ACCESSDENINED,"未授权的访问");
                }
                //解析token
                Claims claims = new JwtUtil().parseJWT(authorization);
                log.info("获取token的信息claims:[{}]",claims);
                String roles = claims.get("roles", String.class);
                log.info("获取角色信息roles:[{}]",roles);
                //获取注解上的权限参数
                String[] permissions = annotation.permissions();
                log.info("注解上的权限参数permissions:[{}]", ArrayUtil.toString(permissions));
                if(permissions.length==0){
                    return true;
                }else {
                    for (int a=0;a<permissions.length;a++){
                        log.info("当前人物角色[{}]vs当前方法角色[{}]",roles,permissions[a]);
                        if(permissions[a].equalsIgnoreCase(roles)){
                            return true;
                        }
                    }
                    throw  new BaseException(StatusCode.ACCESSERROR,"权限不足");
                }
            }
            return true;
        }
    }


}
